{# ----------------------------------------------------------------------------
 # SymForce - Copyright 2022, Skydio, Inc.
 # This source code is under the Apache 2.0 license found in the LICENSE file.
 # ---------------------------------------------------------------------------- #}

#pragma once

#include {{ lcm_type_t_include_dir }}

#include <sym/ops/storage_ops.h>

// Forward declare class, without including header
// We could include the class header here, but we forward declare to be consistent
// with "./group_ops.h", which must forward declare. See that file for an explanation.
namespace sym {
template<typename ScalarType> class {{ cls.__name__ }};
}  // namespace sym

namespace sym {

/**
 * C++ StorageOps implementation for {{ cls }}.
 */
template <typename ScalarType>
struct StorageOps<{{ cls.__name__ }}<ScalarType>> {
  using T = {{ cls.__name__ }}<ScalarType>;
  using Scalar = ScalarType;

  static constexpr int32_t StorageDim() {
    return {{ ops.StorageOps.storage_dim(cls) }};
  }

  static void ToStorage(const T& a, ScalarType* out);
  static T FromStorage(const ScalarType* data);

  static constexpr type_t TypeEnum() {
    return type_t::{{ python_util.camelcase_to_screaming_snakecase(cls.__name__) }};
  }

  {% if "geo" in cls.__module__ %}
  template <typename Generator>
  static T Random(Generator& gen) {
    return T::Random(gen);
  }
  {% endif %}
};

}  // namespace sym

// Explicit instantiation
{% for Scalar in scalar_types %}
extern template struct sym::StorageOps<sym::{{ cls.__name__ }}<{{ Scalar }}>>;
{% endfor %}
